package kotan.view.table;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.table.AbstractTableModel;

import kotan.Kotan;
import kotan.datastore.api.Blob;
import kotan.datastore.api.Key;
import kotan.datastore.api.Text;
import kotan.model.EntityModel;
import kotan.model.KindModel;
import kotan.model.ModelListener;
import kotan.util.ConvertUtil;
import kotan.util.PropertyUtil;

/**
 * TableModel for Entity
 * @author shuji.w6e
 * @since 1.0
 */
public class EntityTableModel extends AbstractTableModel {

    /** logger */
    private static Logger logger = Logger.getLogger(EntityTableModel.class.getName());

    private static final long serialVersionUID = 1L;
    private volatile KindModel kind;

    public EntityModel get(int row) {
        if (row < kind.size()) return kind.get(row);
        return null;
    }

    Key getKey(int rowIndex) {
        return get(rowIndex).getKey();
    }

    KindModel getKind() {
        return kind;
    }

    void setKind(KindModel kind) {
        this.kind = kind;
        kind.getHelper().add(new ModelListener() {

            @Override
            public void onChanged() {
                if (logger.isLoggable(Level.FINE)) logger.fine("KindModel onChanged");
                fireTableStructureChanged();
            }
        });
        fireTableStructureChanged();
    }

    boolean isKey(int col) {
        return kind.isKeyColumn(col);
    }

    boolean isCreateRow(int rowIndex) {
        return kind.size() == rowIndex;
    }

    public boolean isCellSpecialEditable(int rowIndex, int columnIndex) {
        if (isCreateRow(rowIndex)) return false;
        Class<?> t = kind.getPropertyType(rowIndex, columnIndex);
        return t == Text.class || t == Blob.class || t == Key.class;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
     */
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (isCreateRow(rowIndex)) return false;
        return true;
    }

    @Override
    public void setValueAt(Object newValue, int rowIndex, int columnIndex) {
        Object oldValue = kind.getValue(rowIndex, columnIndex);
        Kotan.get().getDatastore().update(kind.get(rowIndex), columnIndex, ConvertUtil.convert(newValue, oldValue));
    }

    void setDefaultValueAt(int row, int column) {
        Class<?> type = kind.getPropertyType(column);
        Object value = PropertyUtil.getDefaultValue(type);
        if (logger.isLoggable(Level.FINE)) logger.fine("setDefaultValueAt: " + value + "," + row + "," + column);
        setValueAt(value, row, column);
    }

    @Override
    public String getColumnName(int column) {
        return kind.getPropertyName(column);
    }

    @Override
    public int getColumnCount() {
        if (kind == null) return 0;
        return kind.propertiesSize();
    }

    @Override
    public int getRowCount() {
        if (kind == null) return 0;
        return kind.size() + 1;
    }

    /**
     * Return the value to which the specified rowIndex and columnIndex.
     * 
     * Return null, if rowIndex is last of model expected first column.
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if (kind == null) return null;
        if (kind.size() <= rowIndex) return null;
        return kind.getValue(rowIndex, columnIndex);
    }

}
